using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using PS.WebParts.Rollup.Query;
using PS.WebParts.Rollup.Utils;

namespace PS.WebParts.Rollup.Query
{
    public class ListSchemaParser
    {
        private string schema;

        public Dictionary<string, string> UserFields { get; private set; }

        public Dictionary<string, UserField> UserMultiFields { get; private set; }

        public Dictionary<string, LookupField> LookupFields { get; private set; }

        public Dictionary<string, string> SimpleFields { get; private set; }

        public List<string> RawFields { get; private set; }

        public Dictionary<string, LookupField> LookupMultiFields { get; private set; }

        private void Reinit()
        {
            schema = null;
            UserFields = new Dictionary<string, string>();
            UserMultiFields = new Dictionary<string, UserField>();
            LookupFields = new Dictionary<string, LookupField>();
            LookupMultiFields = new Dictionary<string, LookupField>();
            SimpleFields = new Dictionary<string, string>();
            RawFields = new List<string>();
        }

        public void ParseDbString(string dbSchema)
        {
            Reinit();
            this.schema = dbSchema.Substring(dbSchema.IndexOf('<'));
            schema = "<Fields>" + schema + "</Fields>";
            ParseSchema();
        }

        private void ParseSchema()
        {
            using (TextReader tr = new StringReader(schema))
            {
                XPathDocument xDoc = new XPathDocument(tr);
                XPathNavigator xNav = xDoc.CreateNavigator();
                XPathNodeIterator xIter = 
                    xNav.Select("//Field[@ColName and @Name] | //FieldRef[@ColName and @Name]");

                int i = 0;
                foreach (XPathNavigator nav in xIter)
                {
                    string columnName = nav.GetAttribute("ColName", string.Empty);
                    string typeName = nav.GetAttribute("Name", string.Empty);
                    typeName = XmlConvert.DecodeName(typeName);

                    string type = nav.GetAttribute("Type", string.Empty);
                    if (type == "User")
                    {
                        SimpleLogger.Write("typeName = {0}, columnName = {1}", typeName, columnName);

                        UserFields.Add(typeName, columnName);
                    }
                    else if (type == "Lookup" || type == "LookupMulti" || type=="UserMulti")
                    {
                        string fieldID = nav.GetAttribute("ID", string.Empty);
                        
                        string sourceListID = type == "UserMulti"
                                                  ? QueryParams.UserMultiSourceListIdStub
                                                  : nav.GetAttribute("List", string.Empty);

                        string sourceListField = type == "UserMulti"
                                                     ? QueryParams.UserMultiUserColumnName + i++
                                                     : XmlConvert.DecodeName(nav.GetAttribute("ShowField", string.Empty));

                        if (!string.IsNullOrEmpty(fieldID) && !string.IsNullOrEmpty(sourceListID) &&
                            !string.IsNullOrEmpty(sourceListField))
                        {
                            var lf = new LookupField
                                                 {
                                                     ColumnnName = columnName,
                                                     Name = typeName,
                                                     ID = fieldID,
                                                     SourceListField = sourceListField,
                                                     SourceListId = sourceListID
                                                 };

                            if(type  == "Lookup")
                                LookupFields.Add(typeName, lf);
                            else
                                LookupMultiFields.Add(typeName, lf);
                        }
                    }
                    else
                    {
                        SimpleFields.Add(typeName, columnName);
                    }
                }

                XPathNodeIterator xRawFieldRefs = xNav.Select("//FieldRef[@Name and not(@ColName)]");

                foreach (XPathNavigator rawFieldRef in xRawFieldRefs)
                {
                    string name = rawFieldRef.GetAttribute("Name", string.Empty);
                    RawFields.Add(name);
                }
            }
        }
    }
}
